﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace lowpolyconv
{
    internal class assimp_toobjmesh
    {
        //从Assimp.Mesh 转换到ObjMesh
        //ObjMesh是我们设计的一个干净的模型格式。
        public static ObjMesh ToObjMesh(Assimp.Mesh item)
        {
            var objmesh = new ObjMesh();
            objmesh.pos = new Vector3[item.VertexCount];
            objmesh.uv = null;
            objmesh.color = null;
            objmesh.normal = null;

            if(item.HasBones)
            {
                objmesh.boneInfos = new BoneInfo[item.VertexCount];
            }
            if(item.HasTangentBasis)
            {
                objmesh.tangent = new Vector3[item.VertexCount];

            }
            if (item.HasNormals)
            {
                objmesh.normal = new Vector3[item.VertexCount];
            }

            if (item.TextureCoordinateChannelCount > 0)
            {
                objmesh.uv = new Vector2[item.VertexCount];
            }
            if (item.HasVertexColors(0))
            {
                objmesh.color = new Color3[item.VertexCount];
            }

            //转换顶点信息到objmesh
            for (var i = 0; i < item.VertexCount; i++)
            {
                objmesh.pos[i].x = item.Vertices[i].X;
                objmesh.pos[i].y = item.Vertices[i].Y;
                objmesh.pos[i].z = item.Vertices[i].Z;

                if (objmesh.normal != null)
                {
                    objmesh.normal[i].x = item.Normals[i].X;
                    objmesh.normal[i].y = item.Normals[i].Y;
                    objmesh.normal[i].z = item.Normals[i].Z;
                }
                if (objmesh.tangent != null)
                {
                    objmesh.tangent[i].x = item.Tangents[i].X;
                    objmesh.tangent[i].y = item.Tangents[i].Y;
                    objmesh.tangent[i].z = item.Tangents[i].Z;
                }
                if (objmesh.uv != null)
                {
                    objmesh.uv[i].x = item.TextureCoordinateChannels[0][i].X;
                    objmesh.uv[i].y = item.TextureCoordinateChannels[0][i].Y;

                }
                if (objmesh.color != null)
                {
                    objmesh.color[i].r = item.VertexColorChannels[0][i].R;
                    objmesh.color[i].g = item.VertexColorChannels[0][i].G;
                    objmesh.color[i].b = item.VertexColorChannels[0][i].B;
                }

            }

            //骨骼信息，assimp的存储不是按顶点的，特殊处理
            if(objmesh.boneInfos!=null)
            {
                for(var bid =0;bid<item.Bones.Count;bid++)
                {

                    var bone = item.Bones[bid];
                    foreach (var bv in bone.VertexWeights)
                    {
                        objmesh.boneInfos[bv.VertexID].AddWeight(bid, bv.Weight);
                    }
                }


                

            }


            //转换面到ObjMesh
            List<Frag> newfrags = new List<Frag>();


            for (var i = 0; i < item.Faces.Count; i++)
            {
                var ii = item.Faces[i].Indices;
                var ic = item.Faces[i].IndexCount;
                if (ic == 3)
                {
                    var fitem = new Frag();


                    //fitem.vcount = 3;
                    fitem.v1 = (uint)ii[0];
                    fitem.v2 = (uint)ii[1];
                    fitem.v3 = (uint)ii[2];
                    newfrags.Add(fitem);

                }
                else if (ic == 4)
                {
                    //if (forcefrag3)
                    {
                        var fitem = new Frag();
                        var fitem2 = new Frag();
                        //fitem.vcount = 3;
                        //fitem2.vcount = 3;
                        fitem.v1 = (uint)ii[0];
                        fitem.v2 = (uint)ii[1];
                        fitem.v3 = (uint)ii[2];
                        fitem2.v1 = (uint)ii[2];
                        fitem2.v2 = (uint)ii[3];
                        fitem2.v3 = (uint)ii[0];
                        newfrags.Add(fitem);
                        newfrags.Add(fitem2);
                    }
                    //else
                    //{
                    //    var fitem = new Frag();


                    //    fitem.vcount = 4;
                    //    fitem.v1 = (uint)ii[0];
                    //    fitem.v2 = (uint)ii[1];
                    //    fitem.v3 = (uint)ii[2];
                    //    fitem.v4 = (uint)ii[3];
                    //    newfrags.Add(fitem);
                    //}

                }
                else
                {
                    throw new Exception("error face.");
                }

            }

            objmesh.frags = newfrags.ToArray();
            return objmesh;
        }

    }
}
